/*
                    Scrollbar Class Implementation
*/
#include "VScrollbar.h"

VScrollbar::VScrollbar()
{
    Image = NULL;
    Scroller = NULL;
    temp = NULL;

    Position = Point(0,0);
    ScrollerPosition = Point(0,0);
    iHeight = 0;
    iWidth = 0;

    iClickY = 0;
    iClickNotches = 0;

    iScrollStartHeight = 0;
    iScrollEndHeight = 0;
    dNotchScrollDistance = 0;
    dCurScrollDistance = 0;
    iTotalScrollDistance = 0;
    iNotches = 0;
    iCurNotch = 0;

    bScrolling = false;
    bScrollEnabled = true;
    bHeightChanged = false;
    bVisible = true;
    bEnabled = true;

    curDist = 0;
}

VScrollbar::~VScrollbar()
{
    SDL_FreeSurface(Image);
    SDL_FreeSurface(Scroller);
    SDL_FreeSurface(temp);
}

int VScrollbar::Initialise(Point NewPosition, string strUFilepath, string strDFilepath,
                                   string strBFilepath, string strSFilepath, int iNewHeight,
                                          int iNewNotches)
{
    temp = OptimiseAlphaSurface(IMG_Load(strBFilepath.c_str()));
    double iZoomFactorX, iZoomFactorY;

    strBackgroundPath = strBFilepath;

    buttonUp.setImage(strUFilepath);
    buttonDown.setImage(strDFilepath);

    Position = NewPosition;
    iHeight = iNewHeight;
    iWidth = buttonUp.getImage()->w;

    iNotches = iNewNotches;

    iZoomFactorY = static_cast<double>(iHeight) / static_cast<double>(temp->h);
    iZoomFactorX = static_cast<double>(iWidth) / static_cast<double>(temp->w);

    Image = zoomSurface(temp, iZoomFactorX, iZoomFactorY, 0);
    Scroller = OptimiseAlphaSurface(IMG_Load(strSFilepath.c_str()));

    bHeightChanged = true;

    CalculateScrollbar();
}

int VScrollbar::CalculateScrollbar()
{
    if (bHeightChanged == true)
    {
        temp = OptimiseAlphaSurface(IMG_Load(strBackgroundPath.c_str()));

        SDL_FreeSurface(Image);

        double iZoomFactorY = iHeight / temp->h;
        double iZoomFactorX = iWidth / temp->w;

        Image = zoomSurface(temp, iZoomFactorX, iZoomFactorY, 0);

        bHeightChanged = false;
    }

    iScrollStartHeight = buttonUp.getImage()->h;
    iScrollEndHeight = iHeight - (buttonDown.getImage()->h + Scroller->h);
    iTotalScrollDistance = iScrollEndHeight - iScrollStartHeight;

    dNotchScrollDistance = static_cast<double>(iTotalScrollDistance) / static_cast<double>(iNotches);

    buttonUp.setPosition(Position);
    buttonDown.setPosition(Point(Position.x, Position.y + (iHeight - buttonDown.getImage()->h)));
}

int VScrollbar::UpdateScroller()
{
    double iCN = static_cast<double>(iCurNotch);
    double iN = static_cast<double>(iNotches);

    double i = ((iCN / iN) * 100);

    double iScrollDistance = (i / 100) * iTotalScrollDistance;

    double x = Position.x;
    double y = (Position.y + iScrollStartHeight) + iScrollDistance;

    ScrollerPosition = Point(x, y);
}

int VScrollbar::BlitToSurface(SDL_Surface *screen)
{
    if (bVisible == true)
    {
        UpdateScroller();

        SDL_Rect dest;
        dest.x = static_cast<int>(Position.x);
        dest.y = static_cast<int>(Position.y);
        SDL_BlitSurface(Image, NULL, screen, &dest);

        if (bScrollEnabled == true)
        {
            dest.x = static_cast<int>(ScrollerPosition.x);
            dest.y = static_cast<int>(ScrollerPosition.y);
            SDL_BlitSurface(Scroller, NULL, screen, &dest);

            buttonUp.BlitToSurface(screen);
            buttonDown.BlitToSurface(screen);
        }
    }
}

int VScrollbar::BlitToFrame(SDL_Surface *surface, Point FramePosition)
{
    if (bVisible == true)
    {
        UpdateScroller();

        SDL_Rect dest;
        dest.x = static_cast<int>(Position.x) + static_cast<int>(FramePosition.x);
        dest.y = static_cast<int>(Position.y) + static_cast<int>(FramePosition.y);
        SDL_BlitSurface(Image, NULL, surface, &dest);

        if (bScrollEnabled == true)
        {
            dest.x = static_cast<int>(ScrollerPosition.x) + static_cast<int>(FramePosition.x);
            dest.y = static_cast<int>(ScrollerPosition.y) + static_cast<int>(FramePosition.y);
            SDL_BlitSurface(Scroller, NULL, surface, &dest);

            buttonUp.BlitToFrame(surface, FramePosition);
            buttonDown.BlitToFrame(surface, FramePosition);
        }
    }
}

int VScrollbar::HandleMouseDown(int iMouseX, int iMouseY)
{
    if (bScrollEnabled == true)
    {
        double xpos = ScrollerPosition.x;
        double ypos = ScrollerPosition.y;

        int iSWidth = Scroller->w;
        int iSHeight = Scroller->h;

        if((iMouseX > xpos) && (iMouseX < xpos + iSWidth) && (iMouseY > ypos) && (iMouseY < ypos + iSHeight))
        {
            bScrolling = true;

            SDL_GetMouseState(NULL, &iClickY);

            iClickNotches = iCurNotch;

            curDist = 0;

            return 1;
        }
        else if (buttonUp.HandleMouseDown(iMouseX, iMouseY) == 1)
        {
             if (iCurNotch > 0)
             {
                iCurNotch--;
             }

             return 1;
        }
        else if (buttonDown.HandleMouseDown(iMouseX, iMouseY) == 1)
        {
             if (iCurNotch < iNotches)
             {
                iCurNotch++;
             }

             return 1;
        }
        else
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }
}

int VScrollbar::HandleMouseUp(int iMouseX, int iMouseY)
{
    buttonUp.HandleMouseUp(iMouseX, iMouseY);
    buttonDown.HandleMouseUp(iMouseX, iMouseY);
    bScrolling = false;
    dCurScrollDistance = 0;

    return 0;
}

int VScrollbar::HandleMouseMotion(int iMouseXREL, int iMouseYREL)
{
    if (bScrolling == true)
    {
        int iMouseY = 0;

        SDL_GetMouseState(NULL, &iMouseY);

        iCurNotch = static_cast<int>(iClickNotches - ((iClickY - iMouseY) / dNotchScrollDistance));

        if (iCurNotch < 0)
        {
            iCurNotch = 0;
        }
        else if (iCurNotch > iNotches)
        {
            iCurNotch = iNotches;
        }

        return 1;
    }

    return 0;
}

void VScrollbar::setHeight(int iNewHeight)
{
     iHeight = iNewHeight;

     bHeightChanged = true;

     CalculateScrollbar();
}

int VScrollbar::getHeight()
{
    return iHeight;
}

void VScrollbar::setPosition(Point NewPosition)
{
     Position = NewPosition;

     CalculateScrollbar();
}

int VScrollbar::getWidth()
{
    return iWidth;
}

void VScrollbar::setNotches(int iNewNotches)
{
    iNotches = iNewNotches;

    if (iCurNotch > iNotches) { iCurNotch = iNotches; }

    CalculateScrollbar();
}

int VScrollbar::getNotches()
{
    return iNotches;
}

Point VScrollbar::getPosition()
{
    return Position;
}

int VScrollbar::getCurNotch()
{
    return iCurNotch;
}

void VScrollbar::AddNotch()
{
    iNotches++;

    CalculateScrollbar();
}

void VScrollbar::RemoveNotch()
{
    iNotches--;

    if (iCurNotch > iNotches) { iCurNotch = iNotches; }

    CalculateScrollbar();
}

void VScrollbar::ScrollToBottom()
{
    iCurNotch = iNotches;
}

void VScrollbar::setScrollEnabled(bool bNewScrollEnabled)
{
    bScrollEnabled = bNewScrollEnabled;
}

int VScrollbar::MoveRelative(double x, double y)
{
    Position.x += x;
    Position.y += y;

    CalculateScrollbar();

    return 0;
}
